<template>
  <div class="basic-form">
    <n-form
      ref="formRef"
      :model="info"
      label-placement="left"
      label-width="auto"
      require-mark-placement="right-hanging"
      :style="{
        maxWidth: '640px',
      }"
    >
      <n-form-item label="Input" path="inputValue">
        <n-input v-model:value="info.inputValue" placeholder="Input" />
      </n-form-item>

      <n-form-item label="Textarea" path="textareaValue">
        <n-input
          v-model:value="info.textareaValue"
          placeholder="Textarea"
          type="textarea"
          :autosize="{
            minRows: 3,
            maxRows: 5,
          }"
        />
      </n-form-item>

      <n-form-item label="Select" path="selectValue">
        <n-select
          v-model:value="info.selectValue"
          placeholder="Select"
          :options="generalOptions"
        />
      </n-form-item>
    </n-form>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed } from "vue";

interface IObj {
  inputValue: string;
  textareaValue: string;
  selectValue: string;
}
interface IProps {
  value: IObj; //一个对象
}

interface IEmits {
  (type: "update:value", value: IObj): void;
}

const props = defineProps<IProps>();
const emits = defineEmits<IEmits>();

const model = ref({
  inputValue: "",
  textareaValue: "",
  selectValue: "",
});
// 实现 props中value的双休数据绑定的一种高级方法，使用proxy对象
const info = computed({
  get() {
    return new Proxy(props.value, {
      // 取指时触发 get 函数不做其他拦截操作 可不写。
      // get(obj, key: keyof IObj) {
      //   console.log("====>>>", "get==", obj, key);
      //   return obj[key];
      // },
      set(obj, key: keyof IObj, value) {
        console.log("改变值", obj, key, value);
        // obj[key] = value;
        emits("update:value", { ...obj, [key]: value });
        return true;
      },
    });
  },
  set() {
    // 不会触发 因为需要改变 info的值才会触发set，改变info里面的某个字段是不会触发的
    console.log("计算属性 set");
  },
});

// 上面这段 computed 代码功能可以封装成一个函数
function useVModel(
  props: any,
  key: string,
  emit: (key: string, args: any) => void
) {
  return computed({
    get() {
      return new Proxy(props[key], {
        // get(obj, key: keyof IObj) {
        //   return obj[key];
        // },
        set(obj, key: keyof IObj, value) {
          console.log("改变值", obj, key, value);
          // obj[key] = value;
          emit("update:" + key, { ...obj, [key]: value });
          return true;
        },
      });
    },
    set(val) {
      // 不会触发 因为需要改变 info的值才会触发set，改变info里面的某个字段是不会触发的
      console.log("计算属性 set");
      emit("update:" + key, { ...val });
    },
  });
}

const generalOptions: any[] = [
  {
    label: "北京",
    value: "beijing",
  },
  {
    label: "上海",
    value: "shanghai",
  },
  {
    label: "广州",
    value: "guangzhou",
  },
  {
    label: "深圳",
    value: "shenzheng",
  },
];
</script>

<style scoped lang="less"></style>
